#include "gen_game_state.h"
#include "fighter.h"
#include "fig_vars.h"
#include "fig_player_craft.h"
#include "fig_sounds.h"
#include "fig_trophie_notification.h"
#include "fig_constants.h"
#include "fig_ui_pausemenu.h"
#include "build.h"
#include "fig_ui_popupmanager.h"

#include "gameflow/ui_popup.h"
#include "ui/ui_progress.h"
#include "gameflow/ui_popup.h"
#include "background/bg_editor.h"	// new luabind can't forward define returned types.
#include "background/bg_scene.h"	
#include "application/game_application.h"
#ifndef PRO_VERSION
#include "admanager/admanager.h"
#endif

#include "dd/dd_man.h"
#include "ui/ui_manager.h"
#include "gameflow/game_flow_manager.h"
#include "script/scripthelper.h"
#include "font/font_manager.h"

			// log
#include "resman/resman.h"				// log

#include "util/timer.h"				
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

#ifdef _ENABLE_LUABIND
#include <luabind/luabind.hpp>
#endif

#include <cassert>

using namespace script;

GENGameState::GENGameState(camera::FbCamera*	pCamera, const std::string& UI, const std::string& OnEnter, const std::string& OnExit ) :
	FIGMOGAUIState(pCamera, UI),
	m_bIsPause(false),
	m_pUI(0),
	m_pFrom(0),
	m_pTo(0),
	m_pGame(NULL),
	m_IsDebugging(false),
	m_IsConstantScreenShot(false),
	m_ConstantScreenShotIndex(0),
	m_ToSkipConstantScreenShot(false),	
	m_DelayFontRecreate(0)
{	
	 
	//StartLevel("foo.lua");
	m_pUIPause = m_Panels[0]->GetWidgetByName("pause_play");
	SetWidgetFunctor("pause_play",UI_DELEGATE(GENGameState, OnButtonPause));
		
	m_pUIBossHealth = (ui::UIProgress*)GetWidget("boss_health_border");
		
  

}




bool	GENGameState::OnEnter()
{


	if(!m_pGame)
		m_pGame = &Fighter::Instance();


	int LevelNum = ((FIGVars*)FIGVars::Instance())->GetCurrentLevel();
	if(LevelNum == 2)
	{
		// hack for ta yote ma
		// fix it later
		//FIGPlayerCraft::Instance().m_SkipAd = true;
	}

	if(FIGUIPopupAnimatorMgr::Instance().GetPopup(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU))
		FIGUIPopupAnimatorMgr::Instance().GetPopup(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU)->Hide();

	FIGSounds::Instance().PlayMusic(FIGSounds::MUSIC_INGAME);

	
	FIGPlayerCraft::Instance().StartNewLevel();


	if(m_pUIBossHealth)
	{
		m_pUIBossHealth->SetIsVisible(false);
		m_pUIBossHealth->SetColor(1.0f,1.0f,1.0f,0.0f);
	}
	


	FIGTrophieNotification::Instance().ForceFinish();

	if (m_pGame) 
		m_pGame->Tick(0);
#if defined(_PLATFORM_ANDROID)

	// only show when the controller is connected
	if(input::MOGAJoystick::Instance().IsConnected())
		FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_CONTROLLER);

#elif  defined(_PLATFORM_WIN32)
	
	// always show so that i can test
	FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_CONTROLLER);

#endif


	_LOG(MSG_COMMENT,"Main GameState On Enter");

	return FIGMOGAUIState::OnEnter();
}
bool	GENGameState::OnExit()
{

	/*if (m_pUI) 
	{
		m_pUI->SetIsVisible(false);
		m_pUI = NULL;
	}
	UTIL_SAFE_DELETE(m_pFrom);
	UTIL_SAFE_DELETE(m_pTo);*/


	if(m_pGame)
	{
		m_pGame->Clear();
		m_pGame = NULL;
	}

	input::Joystick::Instance().JoystickDisable();

#ifndef  PRO_VERSION
	if(FIGVars::Instance()->GetInt(FIGVars::VAR_NAMES_IS_FULL_VERSION) == 0)
		AdManager::Instance().Show();
#endif

//#if defined( _PLATFORM_IOS) || defined(_PLATFORM_ANDROID)
	//res::ResMan::Instance().FlushTexturesExceptUI();	
//#endif
	
#if  defined(_PLATFORM_ANDROID)
	//FontManager::Instance().Recreate();
#endif

	_LOG(MSG_COMMENT,"Main GameState On Enter");

	return gameflow::UIState::OnExit();
}


void	GENGameState::CachedLoad(const std::string& s)
{
	// are we already trying to transition?
	if (m_pFrom || m_pTo) return;

	m_CachedLoad = s;
	// grab a random intro/outro transition, since we're not changing states
	gameflow::GameFlowManager::Instance().GetTransition().GetTransition("", m_pFrom, m_pTo);
	if (!m_pGame)	// if there's already a level, use a half transition
	{
		if (!m_CachedLoad.empty())
		{
			LoadFromFile(m_CachedLoad);
		}
		UTIL_SAFE_DELETE(m_pFrom);
	}
}

void	GENGameState::ClearLevel()
{
	m_pGame->Clear();
}	

bool	GENGameState::Tick(float dt)
{
/*
#ifdef _PLATFORM_ANDROID
	if(m_DelayFontRecreate > 0)
	{
		m_DelayFontRecreate -= dt;
		if( m_DelayFontRecreate < 0)
		{
			FontManager::Instance().Recreate();
			_LOG(MSG_COMMENT,"Force Recreating Fonts");
		}
	}
#endif
*/
	if(dt <= 0 && m_pTo == NULL)
		return gameflow::UIState::Tick(dt);
	

	if(m_IsConstantScreenShot)
	{
		//if(!m_ToSkipConstantScreenShot)
		{
			char	Buffer[256];

			sprintf(Buffer, "screenshots/ac_%08i", m_ConstantScreenShotIndex);
			GetGraphics()->TakeScreenShot(Buffer);
			SDL_Delay(10);
			m_ConstantScreenShotIndex++;
		}
		m_ToSkipConstantScreenShot = !m_ToSkipConstantScreenShot;
	}


	if (m_pFrom)
	{
		m_pFrom->Tick(dt);
		if (m_pFrom->IsOver())
		{
			UTIL_SAFE_DELETE(m_pFrom);
			if (!m_CachedLoad.empty())
			{
				LoadFromFile(m_CachedLoad);
			}
		}
	} else
	if (m_pTo)
	{
		m_pTo->Tick(dt);
		if (m_pTo->IsOver())
		{
			UTIL_SAFE_DELETE(m_pTo);
		}
	}
	// let it update, since we need things like shadows to look proper.
	// we don't really have anything else happening.
	

	if (m_pGame && !m_bIsPause) 
		m_pGame->Tick(dt);
	//GENDebugger::Instance().Tick(dt);

	FIGUIPopupAnimatorMgr::Instance().Tick(dt);

	return gameflow::UIState::Tick(dt);
} 

bool	GENGameState::PreRender()
{
	/*
	if (gameflow::GameFlowManager::Instance().InTransition() || m_pFrom || m_pTo)
	{
		//ui::UIManager::Instance().SetVisible(false);
		if (m_pGame)
		{
			if(rand() % 2 == 0)
				m_pGame->Render();
		}
		else
		{
			//GENIWrapper::Instance().UpdateLoad(false);
		}
		return false;
	} else
	{
		//ui::UIManager::Instance().SetVisible(true);
	}
	*/


	if (m_pGame) 
	{
		m_pGame->Render();
		m_pGame->RenderDebug();
	}


	return UIState::PreRender();
}

bool		GENGameState::PostRender()
{

	bool Ret = UIState::PostRender();

	if (m_pGame) 
		m_pGame->PostRender();

	return Ret;
}



void	GENGameState::MouseScroll(float dt)
{
	/*	if (!g_pApp->MouseInside()) return;
//	if (!m_EnableScroll) return;
	if (!m_pBoard) return;

	// setup the scrolling
	const	float	ScrollBorderMinX = 0.02f;
	const	float	ScrollBorderMaxX = 1.0f - ScrollBorderMinX ;
	const	float	ScrollBorderMinY = 0.02f;
	const	float	ScrollBorderMaxY = 1.0f - ScrollBorderMinY;
	const	float	ScrollSpeed	 = m_pBoard->GetScrollSpeed();

	math::Vec2	P = m_pBoard->GetOffset();
	if (m_FocusPoint.x < ScrollBorderMinX)
	{
		m_pBoard->SetOffset(math::Vec2(P.x - (ScrollSpeed*dt), P.y));
	}else 
	if (m_FocusPoint.x > ScrollBorderMaxX)
	{
		m_pBoard->SetOffset(math::Vec2(P.x + (ScrollSpeed*dt), P.y)); <O(QWWWWWW89annnnnnnmI mmmmmM&2q#&A

	if (m_FocusPoint.y < ScrollBorderMinY)
	{
		m_pBoard->SetOffset(math::Vec2(P.x, P.y - (ScrollSpeed*dt)));  BB@A B&*a	&**(*&a	
	}
	else if (m_FocusPoint.y > ScrollBorderMaxY)
	{
		m_pBoard->SetOffset(math::Vec2(P.x, P.y + (ScrollSpeed*dt)));
	}
*/
}



void		GENGameState::KeyDown(input::Keyboard::KEY* pKey)
{
	if (m_pGame && !m_bIsPause)
	{
		m_pGame->KeyDown(pKey);
	}
	/*	if (!m_pBoard) return;
	switch (pKey->KeyID)
	{

		case KEY_UP : m_pBoard->SetScale(m_pBoard->GetScale() + 0.01f); break;
		case KEY_DOWN : m_pBoard->SetScale(m_pBoard->GetScale() - 0.01f);break;
		case KEY_BACKSPACE : if (m_pEditor) m_pBoard->EndTurn();	break;
	}
	if (m_pEditor)
		m_pEditor->KeyDown(pKey);
*/
	gameflow::UIState::KeyDown(pKey);
}

void		GENGameState::KeyPressed(input::Keyboard::KEY* pKey)
{

	if (m_pGame && !m_bIsPause)
	{
		m_pGame->KeyPressed(pKey);
	}

	switch(pKey->KeyID)
	{
		case KEY_ESCAPE:
		{
			gameflow::UIPopup* pPopup = gameflow::UIPopupManager::Instance().GetPopup("ui/settings.ui");
			if(pPopup && pPopup->IsActive())
			{

			}
			else
			{
				FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU);				
			}
		}
		break;

		case KEY_F6: 
//#ifndef _DEBUG
			m_IsConstantScreenShot = !m_IsConstantScreenShot;
//#endif
		break;
	}

	gameflow::UIState::KeyPressed(pKey);
	
}
void		GENGameState::MouseMove(const math::Vec2& From, const math::Vec2& To)
{
	if(m_bIsPause)
		return;

	if (m_pGame)
	{
		m_pGame->OnMouseMove(From, To);
	}
	m_FocusPoint = To;
/*	if (m_pEditor)
		m_pEditor->MouseMove(From, To);
	if (m_pBoard)
	{
		m_pBoard->MouseMove(From, To);
	}*/
	gameflow::UIState::MouseMove(From,To);
}

void	GENGameState::MouseButtonReleased(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	if (m_pGame && !m_bIsPause)
	{
		m_pGame->MouseButtonReleased(pKey, Pos);
	}
	gameflow::UIState::MouseButtonReleased(pKey,Pos);
}

void	GENGameState::MouseButtonPressed(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	if (m_pGame && !m_bIsPause)
	{
		m_pGame->MouseButtonPressed(pKey, Pos);
	}
/*	if (m_pEditor)
		m_pEditor->MouseButtonPressed(pKey, Pos);
	if (m_pBoard)		
	{
		m_pBoard->MouseButtonPressed(pKey, Pos);
	}*/
	gameflow::UIState::MouseButtonPressed(pKey,Pos);
}

void	GENGameState::MouseButtonDown(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	//if (m_pGame)
	//{
		//m_pGame->MouseButtonDown(pKey, Pos);
	//}
	gameflow::UIState::MouseButtonDown(pKey,Pos);
}

void	GENGameState::MouseWheelMove(int WheelInfo, const math::Vec2& Pos)
{
	gameflow::UIState::MouseWheelMove(WheelInfo,Pos);
}

GENGameState* GENGameState::GetGame()
{
	gameflow::GameFlowManager&	Game = gameflow::GameFlowManager::Instance();
	GENGameState*	pGame = (GENGameState*)Game.GetStateByName("game");
	assert(pGame && "No valid Game state!");
	return pGame;
}




void	GENGameState::LoadFromFile(const std::string& File)
{
	//UTIL_SAFE_DELETE(m_pWorld);
	

	if(m_pGame)
	{
		m_pGame->LoadFromFile(File);	
		//m_pGame->Tick(0);		// do initial updates
	}
	m_CachedLoad.resize(0);	// no longer needed

	//GENSaveGame::Instance().Save(g_pApp->GetSaveFile());
}


void	GENGameState::Save(const std::string& File)
 {
	// if (m_pGame) m_pGame->Save(File); 
 }


static background::BGEditor* GetBGEditor()
{	
/*	gameflow::GameFlowManager&	Game = gameflow::GameFlowManager::Instance();
	GENGameState*	pGame = (GENGameState*)Game.GetStateByName("game");
	GENMapState*	pMap = (GENMapState*)Game.GetStateByName("map");
	gameflow::UIState*	pMenu = (gameflow::UIState*)Game.GetStateByName("MainMenu");


	if (Game.GetCurrentState()==pMap)
	{
		return pMap->GetBG().GetEditor();
	}
	if (Game.GetCurrentState()==pMenu)
	{
		return pMenu->GetBG().GetEditor();
	}
	GENGameWorld*	pWorld = GENGameState::GetWorld();
	if (pWorld)
	{
		if (pWorld->GetBG().GetEditor())	return pWorld->GetBG().GetEditor();
		if (pWorld->GetParallaxBG().GetEditor())	return pWorld->GetParallaxBG().GetEditor();
	}*/
	return background::BGEditor::s_pBGEditor;
}

void GENGameState::Register(LuaPlus::LuaState* _pScript)
{

}


void DELEGATE_CALL		GENGameState::OnButtonPause(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	// this one should be easy to click
	//if(GetLastMouseClickWidget(pWidget) != pWidget)
	//	return;
    FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU);

    
}

void			GENGameState::Pause()
{ 
	m_bIsPause = true; 
	if(m_pUIPause)
		m_pUIPause->SetIsVisible(false);
}

void		GENGameState::UnPause()
{ 
	m_bIsPause = false; 
	if(m_pUIPause)
		m_pUIPause->SetIsVisible(true);
}

void		GENGameState::OnLevelCompete()
{
	FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_GAMEOVER);
	
}


void		GENGameState::LoseFocus()
{
	
	m_bIsPause = true;
	gameflow::UIState::LoseFocus();

	m_DelayFontRecreate = 1.0f;
	FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU);
}

void	GENGameState::OnMOGAKeyDownEvent(int	KeyCode)
{
	//char Buffer[256];
	//sprintf(Buffer,"keycode : %i", KeyCode);
	//_LOG(MSG_COMMENT, Buffer );

	if(FIGUIPopupAnimatorMgr::Instance().OnUIKeyDownEvent(KeyCode))


	{
		// taken
	}
	else
	{

		switch( (input::MOGAJoystick::KEYCODE)KeyCode)
		{
			case input::MOGAJoystick::KEYCODE_BUTTON_START:				
				FIGUIPauseMenu::Instance().Toggle();			
			break;

			case input::MOGAJoystick::KEYCODE_BUTTON_SELECT:		
				FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU);
			break;

			case input::MOGAJoystick::KEYCODE_BUTTON_R2:
				FIGPlayerCraft::Instance().SetIsShootButtonPressed(true);
				break;

			case input::MOGAJoystick::KEYCODE_BUTTON_B:			
				FIGPlayerCraft::Instance().OnControllerBomb();
				break;

			case input::MOGAJoystick::KEYCODE_BUTTON_X:
				FIGPlayerCraft::Instance().SwitchWeapon();
				break;
	            
			case input::MOGAJoystick::KEYCODE_BUTTON_A:
				FIGPlayerCraft::Instance().SetIsShootButtonPressed(true);
				break;

			case input::MOGAJoystick::KEYCODE_BUTTON_Y:
				FIGPlayerCraft::Instance().OnControllerGuardian();
				break;
			
		}
	}
}

void	GENGameState::OnMOGAKeyUpEvent(int	KeyCode)
{
	switch( (input::MOGAJoystick::KEYCODE)KeyCode)
	{
		case input::MOGAJoystick::KEYCODE_BUTTON_R2:				
			FIGPlayerCraft::Instance().SetIsShootButtonPressed(false);
		break;
		
		
	}
}

void	GENGameState::OnMOGAMotionEvent(float X, float Y, float Z)
{
	FIGPlayerCraft::Instance().OnMOGAMotionEvent(X,Y);
}

void	GENGameState::OnMOGAStateEvent(int	State)
{
	gameflow::UIState::OnMOGAStateEvent(State);
	if(input::MOGAJoystick::Instance().IsConnected() == false)
	{
		// connection lost
		// show some text ?
		FIGUIPopupAnimatorMgr::Instance().Show(FIGUIPopupAnimatorMgr::POPUP_NAMES_PAUSEMENU);
	}
	
}


